package com.example.dense_rack_server.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.dense_rack_server.entity.Archives;
import com.example.dense_rack_server.entity.BorrowingRecords;
import com.example.dense_rack_server.entity.Host;
import com.example.dense_rack_server.entity.SysParamset;
import com.example.dense_rack_server.mapper.BorrowingRecordsMapper;
import com.example.dense_rack_server.security.dto.JwtUserDto;
import com.example.dense_rack_server.service.ArchivesService;
import com.example.dense_rack_server.service.HostService;
import com.example.dense_rack_server.service.SysParamsetService;
import com.example.dense_rack_server.utils.AdrAddress;
import com.example.dense_rack_server.utils.CabinetLoginStatus;
import com.example.dense_rack_server.utils.DateFormat;
import com.example.dense_rack_server.utils.Netty.Client;
import com.example.dense_rack_server.utils.Netty.NettyServer;
import com.example.dense_rack_server.utils.Netty.NettyServerHandler;
import com.example.dense_rack_server.utils.Netty.SendCmd;
import com.example.dense_rack_server.utils.ResponseModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 * 手动模式-控制器
 * </p>
 *
 * @author 张彬
 * @since 2025-03-05
 */
@Slf4j
@Controller
@RequestMapping("/hand/movement")
public class HandMovementController {
    @Resource
    public HostService hostService;
    @Resource
    public SendCmd sendCmd;
    @Resource
    private CabinetLoginStatus cabinetLoginStatus;
    @Autowired
    private ArchivesService archivesService;
    @Resource
    public SysParamsetService sysParamsetService;
    @Resource
    public BorrowingRecordsMapper borrowingRecordsMapper;


    /**
     * 手动操作页面
     */
    @GetMapping("index")
    public ModelAndView index() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("HandMovement/index");
        modelAndView.addObject("hostList", hostService.list());
        SysParamset sysParamset = sysParamsetService.getById(2);
        modelAndView.addObject("sysType", sysParamset.getParamValue());
        return modelAndView;
    }

    /**
     * 获取登录状态
     * 没有登录先登录
     * 登陆了就不用登录了
     *
     * @param host
     * @throws InterruptedException
     */
    public void loginStatus(Host host) throws InterruptedException {
        Map<String, Object> loginStatusMap = new LinkedHashMap<>();
        loginStatusMap.put("type", "serverLoginStatus");
        String loginStrMap = JSONUtil.toJsonStr(loginStatusMap);
        sendCmd.send(loginStrMap, null, host.getIp());
        while (true) {
            Thread.sleep(30);
            LinkedHashMap<String, Object> statusMap = cabinetLoginStatus.get();
            log.error("登录状态: " + statusMap);
            if (statusMap.containsKey("serverLoginStatus")) {
                Boolean loginStatus = Convert.toBool(statusMap.get("serverLoginStatus"));
                if (loginStatus) {
                    cabinetLoginStatus.del("serverLoginStatus");
                    break;
                } else {
                    log.info("远程登录");
                    Map<String, Object> loginMap = new LinkedHashMap<>();
                    loginMap.put("type", "serverLogin");
                    String loginMapStr = JSONUtil.toJsonStr(loginMap);
                    sendCmd.send(loginMapStr, null, host.getIp());
                    Thread.sleep(3000);
                    if (statusMap.containsKey("serverLoginStatus")) {
                        cabinetLoginStatus.del("serverLoginStatus");
                    }
                    break;
                }
            }
        }
    }

    /**
     * 获取设备状态
     */
    public boolean getDeviceStatus(Host host) {
        List<String> ipList = NettyServerHandler.getConnectionStatus();
        if (!ipList.contains(host.getIp())) {
            return false;
        }
        return true;
    }

    /**
     * 打开列
     */
    @PostMapping("/openColumn")
    @ResponseBody
    public ResponseModel openColumn(@RequestBody JSONObject data) throws InterruptedException {
        if (StrUtil.isEmpty(data.getStr("hostId")) || StrUtil.isEmpty(data.getStr("column"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        // 设备状态检查
        if (!getDeviceStatus(host)) {
            return ResponseModel.fail("设备未连接，请确认设备开启状态");
        }

        loginStatus(host);
        Map<String, Object> lockMap = new LinkedHashMap<>();
        lockMap.put("type", "mt_unlock");
        String lockStrMap = JSONUtil.toJsonStr(lockMap);
        sendCmd.send(lockStrMap, null, host.getIp());
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("type", "open_lie");

        // 拼接position参数
        StringBuilder position = new StringBuilder();
        int areaCode = host.getCabinetNumber().toString().length();
        if (areaCode == 1) {
            position.append("0").append(host.getCabinetNumber().toString());
        } else {
            position.append(host.getCabinetNumber());
        }
        int columnNumber = data.getStr("column").length();
        if (columnNumber == 1) {
            position.append("0").append(data.getStr("column"));
        } else {
            position.append(data.getStr("column"));
        }
        position.append(data.getStr("denseRackRegion"))
                .append("1").append("1").append("01");


        map.put("position", position.toString());
        String sendMap = JSONUtil.toJsonStr(map);
        sendCmd.send(sendMap, null, host.getIp());
        return ResponseModel.success("密集架第" + host.getCabinetNumber() + "区域，第 " + data.getStr("column") + " 列开始打开");
    }


    /**
     * 单列盘库
     */
    @PostMapping("/singleRowInventory")
    @ResponseBody
    public ResponseModel singleRowInventory(@RequestBody JSONObject data) throws InterruptedException, IOException {
        if (StrUtil.isEmpty(data.getStr("hostId")) || StrUtil.isEmpty(data.getStr("column"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        // 设备状态检查
        if (!getDeviceStatus(host)) {
            return ResponseModel.fail("设备未连接，请确认设备开启状态");
        }
        loginStatus(host);
        JSONObject rfidIpList = JSONUtil.parseObj(host.getRfidList());
        String sendRfidIp = rfidIpList.get("rfidColumn" + data.getStr("column")).toString();

        Map<String, Object> scanMap = new HashMap<>();
        scanMap.put("adr", 0);
        scanMap.put("cd", "scan");
        new Client().send("\n" + JSONUtil.toJsonStr(scanMap), sendRfidIp, false);
        List<Integer> virtualPostionList = Arrays.asList(1, 16);
        // 密集架区
        List<Integer> denseShelfArea = Arrays.asList(0, 1);
        int totalAdr = AdrAddress.calculateTheTotalAdr(host.getCabinetLayer(), host.getCabinetJoint());
        // 获取用户
        JwtUserDto jwtUserDto = (JwtUserDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String userName = jwtUserDto.getUsername();
        new Thread(() -> {
            for (int areaCode : denseShelfArea) {
                for (int joint = 1; joint <= host.getCabinetJoint(); joint++) {
                    for (int layer = 1; layer <= host.getCabinetLayer(); layer++) {
                        for (Integer virtualPostion : virtualPostionList) {
                            String dense_rack_region = areaCode == 1 ? "右" : "左";
                            log.info(" 区号 " + host.getCabinetNumber() + " 列号 " + data.getStr("column") + " 区 " + dense_rack_region +
                                    " 层号 " + layer + " 节数 " + joint + "  开始盘库");
                            int adr = AdrAddress.calculateAdrAddress(host.getCabinetLayer(), host.getCabinetJoint(), layer, joint, virtualPostion);
                            // 计算左区右区
                            if (areaCode == 1) {
                                // 右区
                                adr += totalAdr;
                            }
                            Map<String, Object> rfidMap = new HashMap<>();
                            rfidMap.put("adr", adr);
                            rfidMap.put("cd", "readgroup");
                            JSONObject rfidResult = null;
                            try {
                                rfidResult = new Client().send("\n" + JSONUtil.toJsonStr(rfidMap), sendRfidIp, true);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                            if (rfidResult.size() > 0) {
                                log.info(JSONUtil.toJsonStr(rfidResult));
                                List<String> rfidList = Arrays.asList(rfidResult.getStr("rfid").split(","));
                                int pcdnum = Convert.toInt(rfidResult.getStr("pcdnum"));
                                for (int column = 1; column <= pcdnum; column++) {
                                    int position = column;
                                    if (virtualPostion == 16) {
                                        position = 8 + column;
                                    }
                                    String rfid = rfidList.get(column - 1);
                                    log.info("位置 " + position);
                                    if (!rfid.equals("0000000000")) {
                                        Archives archives = archivesService.getOne(new QueryWrapper<Archives>().eq("file_id", rfid));
                                        if (archives == null) {
                                            // 新增入库的
                                            Archives insertArchives = new Archives();
                                            insertArchives.setFileId(rfid);
                                            insertArchives.setFileName("盘库新增档案-时间" + DateFormat.getDate());
                                            Date date = DateUtil.date();
                                            insertArchives.setYear(Convert.toStr(DateUtil.year(date)));
                                            insertArchives.setUserName(userName);
                                            insertArchives.setStatus(0);
                                            insertArchives.setElectronFileStatus(0);
                                            insertArchives.setCreateTime(DateFormat.getTime());
                                            insertArchives.setUpdateTime(DateFormat.getTime());
                                            insertArchives.setAreaCode(host.getCabinetNumber());
                                            insertArchives.setColumnNumber(data.getInt("column"));
                                            insertArchives.setDenseRackRegion(areaCode);
                                            insertArchives.setJoint(joint);
                                            insertArchives.setLayerNumber(layer);
                                            insertArchives.setPosition(position);
                                            archivesService.save(insertArchives);
                                            // 新增档案日志
                                            BorrowingRecords borrowingRecords = new BorrowingRecords();
                                            borrowingRecords.setFileId(insertArchives.getId());
                                            borrowingRecords.setFileName(insertArchives.getFileName());
                                            borrowingRecords.setDeptId(jwtUserDto.getMyUser().getDeptId());
                                            borrowingRecords.setUserName(userName);
                                            borrowingRecords.setRemarks("盘库新增档案");
                                            borrowingRecords.setCreateTime(DateFormat.getTime());
                                            borrowingRecords.setDataStatus(5);
                                            borrowingRecords.setStatus(1);
                                            borrowingRecords.setModuleType(2);
                                            borrowingRecords.setOperation(userName + "盘库新增" + insertArchives.getFileName() + "档案");
                                            borrowingRecords.setHostId(host.getId());
                                            borrowingRecordsMapper.insert(borrowingRecords);
                                        } else {
                                            // 更新入库的
                                            if (archives.getAreaCode() != host.getCabinetNumber() || archives.getColumnNumber() != data.getInt("column")
                                                    || archives.getJoint() != joint || archives.getLayerNumber() != layer || archives.getPosition() != position) {
                                                // 位置不同
                                                QueryWrapper<Archives> queryWrapper = new QueryWrapper<>();
                                                queryWrapper.eq("area_code", host.getCabinetNumber()).eq("column_number", data.getInt("column"))
                                                        .eq("dense_rack_region", areaCode).eq("joint", joint).eq("layer_number", layer).eq("position", position);
                                                Archives originalLocation = archivesService.getOne(queryWrapper);
                                                if (originalLocation != null) {
                                                    // 原位置存在档案情况下
                                                    originalLocation.setAreaCode(0);
                                                    originalLocation.setColumnNumber(0);
                                                    originalLocation.setDenseRackRegion(0);
                                                    originalLocation.setJoint(0);
                                                    originalLocation.setLayerNumber(0);
                                                    originalLocation.setPosition(0);
                                                    originalLocation.setStatus(1);
                                                    archivesService.updateById(originalLocation);

                                                    // 更新档案信息
                                                    archives.setAreaCode(host.getCabinetNumber());
                                                    archives.setColumnNumber(data.getInt("column"));
                                                    archives.setDenseRackRegion(areaCode);
                                                    archives.setJoint(joint);
                                                    archives.setLayerNumber(layer);
                                                    archives.setPosition(position);
                                                    archives.setStatus(0);
                                                    archivesService.updateById(archives);
                                                } else {
                                                    // 原位置不存在档案情况下
                                                    archives.setAreaCode(host.getCabinetNumber());
                                                    archives.setColumnNumber(data.getInt("column"));
                                                    archives.setDenseRackRegion(areaCode);
                                                    archives.setJoint(joint);
                                                    archives.setLayerNumber(layer);
                                                    archives.setPosition(position);
                                                    archives.setStatus(0);
                                                    archivesService.updateById(archives);
                                                }

                                            }
                                        }

                                    } else {
                                        // 当前位置没有读取到rfid，判断是否存在档案 并处理
                                        QueryWrapper<Archives> queryWrapper = new QueryWrapper<>();
                                        queryWrapper.eq("area_code", host.getCabinetNumber()).eq("column_number", data.getInt("column"))
                                                .eq("dense_rack_region", areaCode).eq("joint", joint).eq("layer_number", layer)
                                                .eq("position", position);
                                        Archives archives = archivesService.getOne(queryWrapper);
                                        if (archives != null) {
                                            if (archives.getStatus() != 1) {
                                                archives.setStatus(1);
                                                archivesService.updateById(archives);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }).start();
        return ResponseModel.success("密集架第" + host.getCabinetNumber() + "区域，第 " + data.getStr("column") + " 列开始后台盘库");
    }

    /**
     * 打开任务指引
     * 目前未启用
     */
    @PostMapping("/openTheTaskGuide")
    @ResponseBody
    public ResponseModel openTheTaskGuide(@RequestBody JSONObject data) throws InterruptedException {
        if (StrUtil.isEmpty(data.getStr("hostId")) || StrUtil.isEmpty(data.getStr("column"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        loginStatus(host);
        Map<String, Object> lockMap = new LinkedHashMap<>();
        lockMap.put("type", "mt_unlock");
        String lockStrMap = JSONUtil.toJsonStr(lockMap);
        sendCmd.send(lockStrMap, null, host.getIp());
        Thread.sleep(200);
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("type", "task_quidexy");
        map.put("position", data.getInt("column"));
        String sendMap = JSONUtil.toJsonStr(map);
        sendCmd.send(sendMap, null, host.getIp());
        return ResponseModel.success("密集架第" + host.getCabinetNumber() + "区域，第 " + data.getStr("column") + " 列开始右移");
    }

    /**
     * 闭架
     */
    @PostMapping("/closedFrame")
    @ResponseBody
    public ResponseModel closedFrame(@RequestBody JSONObject data) throws InterruptedException {
        if (StrUtil.isEmpty(data.getStr("hostId"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        // 设备状态检查
        if (!getDeviceStatus(host)) {
            return ResponseModel.fail("设备未连接，请确认设备开启状态");
        }
        loginStatus(host);
        Map<String, Object> lockMap = new LinkedHashMap<>();
        lockMap.put("type", "mt_unlock");
        String lockStrMap = JSONUtil.toJsonStr(lockMap);
        sendCmd.send(lockStrMap, null, host.getIp());
        Thread.sleep(1000);
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("type", "close_stack");
        String sendMap = JSONUtil.toJsonStr(map);
        sendCmd.send(sendMap, null, host.getIp());
        return ResponseModel.success("密集架开始闭架");
    }

    /**
     * 解锁
     */
    @PostMapping("/unlock")
    @ResponseBody
    public ResponseModel unlock(@RequestBody JSONObject data) throws InterruptedException {
        if (StrUtil.isEmpty(data.getStr("hostId"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        // 设备状态检查
        if (!getDeviceStatus(host)) {
            return ResponseModel.fail("设备未连接，请确认设备开启状态");
        }
        loginStatus(host);
        Map<String, Object> lockMap = new LinkedHashMap<>();
        lockMap.put("type", "mt_unlock");
        String lockStrMap = JSONUtil.toJsonStr(lockMap);
        sendCmd.send(lockStrMap, null, host.getIp());
        return ResponseModel.success("密集架已解锁");
    }

    /**
     * 锁定
     */
    @PostMapping("/lock")
    @ResponseBody
    public ResponseModel lock(@RequestBody JSONObject data) throws InterruptedException {
        if (StrUtil.isEmpty(data.getStr("hostId"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        // 设备状态检查
        if (!getDeviceStatus(host)) {
            return ResponseModel.fail("设备未连接，请确认设备开启状态");
        }
        loginStatus(host);
        Map<String, Object> lockMap = new LinkedHashMap<>();
        lockMap.put("type", "mt_lock");
        String lockStrMap = JSONUtil.toJsonStr(lockMap);
        sendCmd.send(lockStrMap, null, host.getIp());
        return ResponseModel.success("密集架已锁定");
    }

    /**
     * 通风
     */
    @PostMapping("/airChange")
    @ResponseBody
    public ResponseModel airChange(@RequestBody JSONObject data) throws InterruptedException {
        if (StrUtil.isEmpty(data.getStr("hostId"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        // 设备状态检查
        if (!getDeviceStatus(host)) {
            return ResponseModel.fail("设备未连接，请确认设备开启状态");
        }
        loginStatus(host);
        Map<String, Object> lockMap = new LinkedHashMap<>();
        lockMap.put("type", "air_change");
        String lockStrMap = JSONUtil.toJsonStr(lockMap);
        sendCmd.send(lockStrMap, null, host.getIp());
        return ResponseModel.success("密集架正在通风");
    }

    /**
     * 停止
     */
    @PostMapping("/mtStop")
    @ResponseBody
    public ResponseModel mtStop(@RequestBody JSONObject data) throws InterruptedException {
        if (StrUtil.isEmpty(data.getStr("hostId"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        // 设备状态检查
        if (!getDeviceStatus(host)) {
            return ResponseModel.fail("设备未连接，请确认设备开启状态");
        }
        loginStatus(host);
        Map<String, Object> lockMap = new LinkedHashMap<>();
        lockMap.put("type", "mt_stop");
        String lockStrMap = JSONUtil.toJsonStr(lockMap);
        sendCmd.send(lockStrMap, null, host.getIp());
        return ResponseModel.success("密集架正在停止");
    }

    /**
     * 退出登录
     */
    @PostMapping("/loginOut")
    @ResponseBody
    public ResponseModel loginOut(@RequestBody JSONObject data) throws InterruptedException {
        if (StrUtil.isEmpty(data.getStr("hostId"))) {
            return ResponseModel.fail("缺少参数");
        }
        Host host = hostService.getById(data.getInt("hostId"));
        // 设备状态检查
        if (!getDeviceStatus(host)) {
            return ResponseModel.fail("设备未连接，请确认设备开启状态");
        }
        loginStatus(host);
        Map<String, Object> lockMap = new LinkedHashMap<>();
        lockMap.put("type", "serverLoginOut");
        String lockStrMap = JSONUtil.toJsonStr(lockMap);
        sendCmd.send(lockStrMap, null, host.getIp());
        return ResponseModel.success("密集架已退出登录");
    }

    /**
     * 获取主机详情信息
     */
    @PostMapping("/column/info")
    @ResponseBody
    public ResponseModel getHostDetail(@RequestBody JSONObject data) throws InterruptedException {
        Host host = hostService.getById(data.getInt("hostId"));
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("ip", host.getIp());
        resMap.put("cabinetName", host.getCabinetName());
        resMap.put("cabinetNumber", host.getCabinetNumber());
        resMap.put("columnNumber", host.getColumnNumber());
        resMap.put("cabinetJoint", host.getCabinetJoint());
        resMap.put("cabinetLayer", host.getCabinetLayer());
//        ArchivesArea archivesArea = archivesAreaService.getById(host.getAreaId());
//        resMap.put("areaName",archivesArea.getAreaName());

        List<Archives> archivesList = archivesService.list(new QueryWrapper<Archives>()
                .eq("area_code", host.getCabinetNumber()).eq("column_number", data.getInt("column")));
        int borrowCount = 0;
        int restoreCount = 0;
        for (Archives archive : archivesList) {
            if (archive.getStatus() == 1 || archive.getStatus() == 3) {
                borrowCount++;
            } else if (archive.getStatus() == 0 || archive.getStatus() == 2) {
                restoreCount++;
            }
        }
        resMap.put("borrowCount", borrowCount);
        resMap.put("restoreCount", restoreCount);
        resMap.put("archiveTotal", archivesList.size());

        return ResponseModel.success(resMap);
    }


}
